using System;
using System.Text.RegularExpressions;
using System.Web.Caching;
using StackExchange.Redis;

namespace Aricie.DNN.Caching.Client.RedisCachingProvider
{
    public class RedisCallBackAdapter : CacheCallBackAdapter
    {

        private static Regex _KeySpaceRegex = new Regex("__keyevent\\@\\d+__\\:(?<command>.+)", RegexOptions.CultureInvariant | RegexOptions.Compiled);

        private RedisClientProvider _RedisProvider;

        public RedisCallBackAdapter(CacheItemRemovedCallback itemRemovedCallBack, RedisClientProvider provider)
            : base(itemRemovedCallBack)
        {
            _RedisProvider = provider;
        }



        public void ProcessMessage(RedisChannel redisChannel, RedisValue redisValue)
        {
            try
            {
                string channelKey = redisChannel.ToString();
                string channelValue = redisValue.ToString();
                switch (_RedisProvider.SpecificClusterSettings.CallbackMode)
                {
                    case RedisCallbackMode.CustomChannel:
                        if (channelKey.StartsWith(_RedisProvider.SpecificClusterSettings.CallbackChannel))
                        {
                            if (!_RedisProvider.SpecificClusterSettings.CallbackChannelIncludeFingerPrint
                                || RedisClientProvider.Guid.ToString() != channelKey.Replace(_RedisProvider.SpecificClusterSettings.CallbackChannel + ":", ""))
                            {
                                this.OnCacheNotificationCallBack(channelValue, null, CacheItemRemovedReason.Removed);
                            }
                        }
                        break;
                    case RedisCallbackMode.KeyspaceNotifications:
                       var regexMatch = _KeySpaceRegex.Match(channelKey);
                       if (regexMatch.Success)
                       {
                           var strCommand = regexMatch.Groups["command"].Value.ToLowerInvariant();
                           if (strCommand == "del")
                           {
                               this.OnCacheNotificationCallBack(channelValue, null, CacheItemRemovedReason.Removed);
                           }
                       }

                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
            catch (Exception ex)
            {
                _RedisProvider.ProcessException(ex, "Redis Exception", true);
            }
        }

    }
}